import crypto from 'crypto';
import JSONbig from 'json-bigint';
import { Logger, AppError, ErrorCode } from '../utils/logger';

// 汇沣支付配置
export interface HuifengPayConfig {
  merchantId: string;
  secretKey: string;
  baseUrl: string;
  notifyUrl: string;
  collectionPayType?: string;
  payoutPayType?: string;
  country?: string;
  defaultUserIp?: string;
  fallbackEmail?: string;
  fallbackPhone?: string;
}

// 创建代收订单请求参数
export interface CreateHuifengOrderRequest {
  userId: number;
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  transAccNo: string; // 银行卡号
  paymentName: string; // 付款人姓名
  bankCode: string; // 银行编码
  customerEmail?: string;
  customerPhone?: string;
  extendParam?: string;
  customerIp?: string;
}

// 创建代付订单请求参数
export interface CreateHuifengPayoutRequest {
  amount: number;
  paymentMethod: 'BankTransfer' | 'qrPay';
  orderId: string;
  receiverName: string; // 收款人姓名
  receiverBankCard: string; // 收款银行卡号
  bankCode: string; // 银行编码
  accountName?: string; // 账户名称
  bankName?: string; // 银行名称
  certificate?: string; // 证件号
  subbranch?: string; // 支行名称
  customerEmail?: string;
  customerPhone?: string;
  userIp?: string;
  extra?: string; // 扩展字段(JSON字符串)
  remark?: string;
}

// 汇沣支付代收响应
export interface HuifengOrderResponse {
  code: number;
  message: string;
  data?: {
    order_num: string;
    pay_url: string;
    type: number; // 1=url, 2=二维码
    qr_code?: string; // base64二维码
  };
}

// 汇沣支付代付响应
export interface HuifengPayoutResponse {
  code: number;
  message: string;
  data?: {
    order_num: string;
    status?: string;
  };
}

// 汇沣支付订单查询响应
export interface HuifengQueryResponse {
  code: number;
  message: string;
  data?: {
    order_num: string;
    merchant_order_num: string;
    amount: string;
    status: number; // 200=成功, 999=失败, 666=超时
    pay_succ_time?: string;
  };
}

export class HuifengPayService {
  private config: HuifengPayConfig;

  constructor(config: HuifengPayConfig) {
    this.config = config;
  }

  /**
   * 生成签名
   */
  private generateSign(params: Record<string, any>, excludeKeys: string[] = ['sign']): string {
    try {
      // 1. 过滤空值和排除的key
      const filteredParams = Object.keys(params)
        .filter(key => !excludeKeys.includes(key) && params[key] !== undefined && params[key] !== '')
        .sort() // 2. 按字典序排序
        .reduce((obj, key) => {
          obj[key] = params[key];
          return obj;
        }, {} as Record<string, any>);

      // 3. 构建参数字符串
      const paramString = Object.keys(filteredParams)
        .map(key => `${key}=${filteredParams[key]}`)
        .join('&');

      // 4. 添加密钥
      const signString = paramString
        ? `${paramString}&key=${this.config.secretKey}`
        : `key=${this.config.secretKey}`;

      Logger.info('汇沣支付签名原始字符串', { signString: signString.replace(this.config.secretKey, '***SECRET***') });

      // 5. MD5加密并转大写
      const sign = crypto.createHash('md5').update(signString).digest('hex').toUpperCase();

      Logger.info('汇沣支付生成签名', { sign });

      return sign;
    } catch (error) {
      Logger.error('汇沣支付签名生成失败', error);
      throw new AppError('签名生成失败', ErrorCode.PAYMENT_SIGN_ERROR);
    }
  }

  /**
   * 验证签名
   */
  private verifySign(params: Record<string, any>, receivedSign: string): boolean {
    try {
      const calculatedSign = this.generateSign(params);
      const isValid = calculatedSign === receivedSign;

      Logger.info('汇沣支付签名验证', {
        calculated: calculatedSign,
        received: receivedSign,
        isValid
      });

      return isValid;
    } catch (error) {
      Logger.error('汇沣支付签名验证失败', error);
      return false;
    }
  }

  /**
   * 发送HTTP请求
   */
  private async sendRequest(url: string, data: any): Promise<any> {
    try {
      Logger.info('汇沣支付请求', { url, data: { ...data, sign: '***' } });

      // 构建JSON请求体，保持BigInt类型
      const requestBody: Record<string, any> = {};

      Object.keys(data).forEach(key => {
        if (data[key] !== undefined && data[key] !== '') {
          requestBody[key] = data[key];
        }
      });

      Logger.info('汇沣支付JSON请求体详情', {
        merchantId: requestBody.merchantId?.toString(),
        merchantIdType: typeof requestBody.merchantId,
        payType: requestBody.payType,
        payTypeType: typeof requestBody.payType
      });

      // 使用 json-bigint 序列化，保持大整数精度
      const jsonBody = JSONbig.stringify(requestBody);

      Logger.info('汇沣支付最终JSON字符串', { jsonBody });

      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'User-Agent': 'TaiGuoChongZhiSystem/1.0'
        },
        body: jsonBody
      });

      if (!response.ok) {
        let rawBody: string | undefined;
        let parsedBody: unknown;

        try {
          rawBody = await response.text();
          if (rawBody) {
            parsedBody = JSON.parse(rawBody);
          }
        } catch (parseError) {
          Logger.warn('汇沣支付错误响应解析失败', {
            url,
            status: response.status,
            parseError: parseError instanceof Error ? parseError.message : parseError
          });
        }

        throw new AppError(`HTTP请求失败: ${response.status}`, ErrorCode.PAYMENT_API_ERROR, {
          url,
          responseBody: parsedBody ?? rawBody
        });
      }

      const result = await response.json();
      Logger.info('汇沣支付响应', { result });

      return result;
    } catch (error) {
      Logger.error('汇沣支付请求失败', error);
      throw error instanceof AppError ? error : new AppError('网络请求失败', ErrorCode.PAYMENT_API_ERROR);
    }
  }

  /**
   * 生成订单号
   */
  generateOrderId(): string {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substring(2, 8).toUpperCase();
    return `HF${timestamp}${random}`;
  }

  /**
   * 创建代收订单
   */
  async createRechargeOrder(request: CreateHuifengOrderRequest): Promise<HuifengOrderResponse> {
    try {
      Logger.info('汇沣支付创建代收订单', { orderId: request.orderId, amount: request.amount });

      // 使用配置的回调地址，如果未配置则使用默认地址
      const notifyUrl = this.config.notifyUrl && this.config.notifyUrl !== 'your_notify_url'
        ? this.config.notifyUrl
        : `${process.env.APP_BASE_URL || 'https://52.77.253.74:3017'}/api/callback/huifeng`;

      const payType = (this.config.collectionPayType || '274120').toString();
      const country = (this.config.country || 'TH').toString();
      const email = request.customerEmail?.trim() ||
                     this.config.fallbackEmail?.trim() ||
                     'customer@taiguo-recharge.com';
      const phone = request.customerPhone?.trim() ||
                    this.config.fallbackPhone?.trim() ||
                    '+66123456789';
      const userIp = request.customerIp?.trim() || this.config.defaultUserIp || '127.0.0.1';

      // 详细日志merchant ID的处理过程
      Logger.info('汇沣支付商户ID处理详情', {
        originalMerchantId: this.config.merchantId,
        merchantIdType: typeof this.config.merchantId,
        merchantIdLength: this.config.merchantId?.length,
        payType: payType,
        payTypeType: typeof payType
      });

      // 验证merchantId是否为有效数字，使用BigInt确保精度
      if (!this.config.merchantId || !/^\d+$/.test(this.config.merchantId)) {
        throw new AppError('商户ID格式错误，必须是纯数字', ErrorCode.PAYMENT_CONFIG_ERROR);
      }

      // 使用 BigInt 保持精度（配合 json-bigint 序列化）
      const merchantIdBigInt = BigInt(this.config.merchantId);

      Logger.info('汇沣支付商户ID处理策略', {
        originalMerchantId: this.config.merchantId,
        bigIntValue: merchantIdBigInt.toString(),
        dataType: 'bigint',
        precisionLoss: false,
        strategy: 'use_bigint_with_json-bigint'
      });

      const requestData: Record<string, any> = {
        merchantId: merchantIdBigInt, // 使用 BigInt 保持精度
        payType: parseInt(payType), // 转换为int数字类型
        orderId: request.orderId,
        amount: request.amount.toFixed(2),
        notifyUrl: notifyUrl,
        country,
        userName: request.paymentName,
        accNo: request.transAccNo,
        bankCode: request.bankCode,
        email,
        phone,
        user_ip: userIp
      };

      Logger.info('汇沣支付最终请求数据详情', {
        merchantId: requestData.merchantId,
        merchantIdType: typeof requestData.merchantId,
        payType: requestData.payType,
        payTypeType: typeof requestData.payType,
        allKeys: Object.keys(requestData),
        requestDataStringified: JSON.stringify(
          requestData,
          (_, value) => (typeof value === 'bigint' ? value.toString() : value),
          2
        )
      });

      if (request.extendParam) {
        requestData.extra = request.extendParam;
      }

      // 生成签名
      (requestData as any)['sign'] = this.generateSign(requestData);

      // 发送请求
      const url = `${this.config.baseUrl}/pay/collection/create`;
      const response = await this.sendRequest(url, requestData);

      return response as HuifengOrderResponse;
    } catch (error) {
      Logger.error('汇沣支付创建代收订单失败', error, { orderId: request.orderId });
      throw error;
    }
  }

  /**
   * 创建代付订单
   */
  async createPayoutOrder(request: CreateHuifengPayoutRequest): Promise<HuifengPayoutResponse> {
    try {
      Logger.info('汇沣支付创建代付订单', { orderId: request.orderId, amount: request.amount });

      // 使用配置的回调地址，如果未配置则使用默认地址
      const notifyUrl = this.config.notifyUrl && this.config.notifyUrl !== 'your_notify_url'
        ? this.config.notifyUrl
        : `${process.env.APP_BASE_URL || 'https://52.77.253.74:3017'}/api/callback/huifeng`;

      const payType = (this.config.payoutPayType || this.config.collectionPayType || '90801').toString();
      const country = (this.config.country || 'TH').toString();
      const phone = request.customerPhone?.trim() || this.config.fallbackPhone?.trim();
      const email = request.customerEmail?.trim() || this.config.fallbackEmail?.trim();
      const userIp = request.userIp?.trim() || this.config.defaultUserIp || '127.0.0.1';

      // 验证merchantId是否为有效数字
      if (!this.config.merchantId || !/^\d+$/.test(this.config.merchantId)) {
        throw new AppError('商户ID格式错误，必须是纯数字', ErrorCode.PAYMENT_CONFIG_ERROR);
      }

      // 使用 BigInt 保持精度（配合 json-bigint 序列化）
      const merchantIdBigInt = BigInt(this.config.merchantId);

      const requestData: Record<string, any> = {
        merchantId: merchantIdBigInt, // 使用 BigInt 保持精度
        payType: parseInt(payType), // 转换为int数字类型
        sourceOrderId: request.orderId,
        price: request.amount.toFixed(2),
        notifyUrl: notifyUrl,
        country,
        bankCode: request.bankCode,
        accountNo: request.receiverBankCard,
        userName: request.receiverName
      };

      const accountName = request.accountName?.trim() || request.receiverName;
      if (accountName) {
        requestData.accountName = accountName;
      }

      if (request.bankName?.trim()) {
        requestData.bankName = request.bankName.trim();
      }

      if (phone) {
        requestData.phone = phone;
      }

      if (email) {
        requestData.email = email;
      }

      if (userIp) {
        requestData.user_ip = userIp;
      }

      if (request.certificate?.trim()) {
        requestData.certificate = request.certificate.trim();
      }

      if (request.subbranch?.trim()) {
        requestData.subbranch = request.subbranch.trim();
      }

      if (request.extra?.trim()) {
        requestData.extra = request.extra.trim();
      }

      // 生成签名
      (requestData as any)['sign'] = this.generateSign(requestData);

      // 发送请求
      const url = `${this.config.baseUrl}/pay/create`;
      const response = await this.sendRequest(url, requestData);

      return response as HuifengPayoutResponse;
    } catch (error) {
      Logger.error('汇沣支付创建代付订单失败', error, { orderId: request.orderId });
      throw error;
    }
  }

  /**
   * 查询订单状态
   */
  async queryOrder(orderNum: string, merchantOrderNum: string): Promise<HuifengQueryResponse> {
    try {
      Logger.info('汇沣支付查询订单', { orderNum, merchantOrderNum });

      // 验证merchantId是否为有效数字
      if (!this.config.merchantId || !/^\d+$/.test(this.config.merchantId)) {
        throw new AppError('商户ID格式错误，必须是纯数字', ErrorCode.PAYMENT_CONFIG_ERROR);
      }

      // 使用 BigInt 保持精度（配合 json-bigint 序列化）
      const merchantIdBigInt = BigInt(this.config.merchantId);

      const requestData = {
        merchantId: merchantIdBigInt, // 使用 BigInt 保持精度
        order_num: orderNum,
        merchant_order_num: merchantOrderNum
      };

      // 生成签名
      (requestData as any)['sign'] = this.generateSign(requestData);

      // 发送请求 - 代收查询
      const url = `${this.config.baseUrl}/pay/collection/query`;
      const response = await this.sendRequest(url, requestData);

      return response as HuifengQueryResponse;
    } catch (error) {
      Logger.error('汇沣支付查询订单失败', error, { orderNum, merchantOrderNum });
      throw error;
    }
  }

  /**
   * 查询代付订单状态
   */
  async queryPayoutOrder(orderNum: string, merchantOrderNum: string): Promise<HuifengQueryResponse> {
    try {
      Logger.info('汇沣支付查询代付订单', { orderNum, merchantOrderNum });

      // 验证merchantId是否为有效数字
      if (!this.config.merchantId || !/^\d+$/.test(this.config.merchantId)) {
        throw new AppError('商户ID格式错误，必须是纯数字', ErrorCode.PAYMENT_CONFIG_ERROR);
      }

      // 使用 BigInt 保持精度（配合 json-bigint 序列化）
      const merchantIdBigInt = BigInt(this.config.merchantId);

      const requestData = {
        merchantId: merchantIdBigInt, // 使用 BigInt 保持精度
        order_num: orderNum,
        merchant_order_num: merchantOrderNum
      };

      // 生成签名
      (requestData as any)['sign'] = this.generateSign(requestData);

      // 发送请求 - 代付查询
      const url = `${this.config.baseUrl}/pay/payment/query`;
      const response = await this.sendRequest(url, requestData);

      return response as HuifengQueryResponse;
    } catch (error) {
      Logger.error('汇沣支付查询代付订单失败', error, { orderNum, merchantOrderNum });
      throw error;
    }
  }

  /**
   * 验证回调通知
   */
  verifyNotification(data: any): boolean {
    try {
      Logger.info('汇沣支付验证回调通知', { data });

      if (!data.sign) {
        Logger.error('汇沣支付回调缺少签名');
        return false;
      }

      const receivedSign = data.sign;
      return this.verifySign(data, receivedSign);
    } catch (error) {
      Logger.error('汇沣支付回调验证失败', error);
      return false;
    }
  }

  /**
   * 查询账户余额
   */
  async queryBalance(): Promise<any> {
    try {
      Logger.info('汇沣支付查询余额');

      // 验证merchantId是否为有效数字
      if (!this.config.merchantId || !/^\d+$/.test(this.config.merchantId)) {
        throw new AppError('商户ID格式错误，必须是纯数字', ErrorCode.PAYMENT_CONFIG_ERROR);
      }

      // 使用 BigInt 保持精度（配合 json-bigint 序列化）
      const merchantIdBigInt = BigInt(this.config.merchantId);

      const requestData = {
        merchantId: merchantIdBigInt // 使用 BigInt 保持精度
      };

      // 生成签名
      (requestData as any)['sign'] = this.generateSign(requestData);

      // 发送请求
      const url = `${this.config.baseUrl}/pay/balance/query`;
      const response = await this.sendRequest(url, requestData);

      return response;
    } catch (error) {
      Logger.error('汇沣支付查询余额失败', error);
      throw error;
    }
  }
}

/**
 * 检查汇沣支付是否已配置
 */
export function isHuifengConfigured(): boolean {
  return !!(
    process.env.HUIFENG_MERCHANT_ID &&
    process.env.HUIFENG_SECRET_KEY &&
    process.env.HUIFENG_BASE_URL &&
    process.env.HUIFENG_NOTIFY_URL
  );
}

/**
 * 创建汇沣支付服务实例
 */
export function createHuifengPayService(): HuifengPayService {
  if (!isHuifengConfigured()) {
    throw new AppError('汇沣支付未配置', ErrorCode.PAYMENT_CONFIG_ERROR);
  }

  const config: HuifengPayConfig = {
    merchantId: process.env.HUIFENG_MERCHANT_ID!,
    secretKey: process.env.HUIFENG_SECRET_KEY!,
    baseUrl: process.env.HUIFENG_BASE_URL!,
    notifyUrl: process.env.HUIFENG_NOTIFY_URL!,
    collectionPayType: process.env.HUIFENG_COLLECTION_PAY_TYPE,
    payoutPayType: process.env.HUIFENG_PAYOUT_PAY_TYPE,
    country: process.env.HUIFENG_COUNTRY,
    defaultUserIp: process.env.HUIFENG_DEFAULT_USER_IP,
    fallbackEmail: process.env.HUIFENG_DEFAULT_EMAIL,
    fallbackPhone: process.env.HUIFENG_DEFAULT_PHONE,
  };

  return new HuifengPayService(config);
}
